require("constant")
require("utility_functions")
local block = require "block"
local M = {}

function M.initDataSystem()

	GameRules.pdata = {} --玩家所拥有的城市ID
	for i=1,MAX_PLAYER do
		local t = {}
		table.insert(GameRules.pdata,t)
	end
	GameRules.golds = {0,0,0,0,0,0,0,0,0,0}
	for i=1,MAX_PLAYER do
		GameRules.golds[i] = INIT_GOLD
	end
	--M.cancleTrade()

end

function M.getOwner( idx )
	return GameRules.blocks[idx].owner
end

function M.getCitiesById( id )
	local cities = GameRules.pdata[id+1]
	local ret = {}
	for i,city in ipairs(cities) do
		local t = M.getCityById(city)
		t.city = city
		table.insert(ret,t)
	end
	return ret
end

function M.getCityById( id )
	local city = GameRules.blocks[id]
	return city
end
--添加物品
function M.addCityById( id,itemIndex )
	table.insert(GameRules.pdata[id+1],itemIndex)
	GameRules.blocks[itemIndex].owner = id
	local infos = {}
	local t = {
		playerid = id,
		cities = M.getCitiesById(id),
	}
	table.insert(infos,t)
	local hero = PlayerResource:GetSelectedHeroEntity(id)
	local pos = GetGroundPosition(GameRules.blocks[itemIndex].partPos,hero)
	if GameRules.blocks[itemIndex].partID then
		ParticleManager:DestroyParticle(GameRules.blocks[itemIndex].partID,false)
	end
	local partID = ParticleManager:CreateParticle("particles/items2_fx/owner_tp.vpcf", PATTACH_ABSORIGIN,hero )
	ParticleManager:SetParticleControlEnt(partID, 3, hero, PATTACH_ABSORIGIN, "follow_origin", pos, true)
	ParticleManager:SetParticleControl(partID,0,pos)
	ParticleManager:SetParticleControl(partID,4,Vector(1,0,0))
	ParticleManager:SetParticleControl(partID, 5, pos)
	ParticleManager:SetParticleControl(partID,6,Vector(255,255,255))

	GameRules.blocks[itemIndex].partID = partID
	CustomGameEventManager:Send_ServerToAllClients("S2C_UPDATE_PLAYER_INFO", {infos = infos})
end
--移除物品
function M.removeCityById( id,itemIndex )
	GameRules.blocks[itemIndex].owner = nil
	for i,v in ipairs(GameRules.pdata[id+1]) do
		if v == itemIndex then
			table.remove(GameRules.pdata[id+1],i)
			break
		end
	end
	local infos = {}
	local t = {
		playerid = id,
		cities = M.getCitiesById(id),
	}
	table.insert(infos,t)
	ParticleManager:DestroyParticle(GameRules.blocks[itemIndex].partID, true)
	GameRules.blocks[itemIndex].partID = nil
	CustomGameEventManager:Send_ServerToAllClients("S2C_UPDATE_PLAYER_INFO", {infos = infos})
end

function M.removeCitiesById( id )
	for i,v in ipairs(GameRules.pdata[id+1]) do
		M.removeCityById(id,v)
	end
end

--出售房子 降级 获得50%返还
function M.delvCityById( id,itemIndex,dontEffect )
	if GameRules.blocks[itemIndex].lv > 1 then
		GameRules.blocks[itemIndex].lv = GameRules.blocks[itemIndex].lv - 1
		local block = GameRules.blocks[itemIndex]
		block.house:SetOriginalModel(MODEL_HOUSE[GameRules.blocks[itemIndex].lv])
		block.house:SetModel(MODEL_HOUSE[GameRules.blocks[itemIndex].lv])
		block.house:SetModelScale(0.1)
		block.house:SetAngles(0, 90, 0)
		if not dontEffect then
			local cost = block.buildcost or block.gold or 0
			ModifyGoldLtx(id,math.floor(cost/2))
		end
		EmitSoundOn("Damage_Melee.Building",block.house)
		return true
	else
		return false
	end
	--动画表现 TODO
end
function M.lvupCityById( id,itemIndex,dontEffect )
	local city = GameRules.blocks[itemIndex]
	if city.lv and city.build and city.lv < #city.build and city.diya ~= true then
		if not dontEffect then
			local cost = city.buildcost or city.gold or 0
			local curgold = _getGold(id)
			if curgold < cost then
				showWarn("#TIP_NO_GOLD",id)
				return false
			end
			ModifyGoldLtx(id,-cost)
		end
		city.lv = city.lv + 1
		--TODO 建筑升级表现
		local modelName = MODEL_HOUSE[city.lv]
		if not city.house then
			local pos = city.bannerpos
			local house = CreateUnitByName("npc_house", pos, true, nil, nil, DOTA_TEAM_GOODGUYS)
			city.house = house
			house:SetAbsOrigin(pos+Vector(0,0,10))
			city.house:SetAngles(0, 90, 0)
		end
		city.house:SetOriginalModel(MODEL_HOUSE[city.lv])
		city.house:SetModel(MODEL_HOUSE[city.lv])
		city.house:SetModelScale(0.1)

		local pts = ParticleManager:CreateParticle("particles/econ/items/monkey_king/arcana/water/mk_spring_water_splash.vpcf",PATTACH_ABSORIGIN,city.house)
		ParticleManager:SetParticleControl(pts,0,city.bannerpos)

		EmitSoundOn("Damage_Melee.Building",city.house)
		return true
	end
	return false
end
--抵押物品
function M.diyaCityById( id,itemIndex,dontEffect )
	local city = GameRules.blocks[itemIndex]
	if city.owner ~= id or city.diya == true then
		return false
	end
	city.diya = true
	changeModelColor(itemIndex,Vector(255,0,0))
	CustomGameEventManager:Send_ServerToAllClients("S2C_CITY_DIYA",{itemIndex = itemIndex,opt = 1})
	if not dontEffect then
		ModifyGoldLtx(id,math.floor((city.gold or 0) / 2))
	end
end
--赎回物品
function M.shCityById( id,itemIndex,dontEffect )
	local city = GameRules.blocks[itemIndex]
	local curgold = _getGold(id)
	local needgold = math.floor((city.gold or 0) / 2)
	if city.owner ~= id or city.diya ~= true or curgold < needgold then
		return false
	end
	city.diya = false
	changeModelColor(itemIndex,Vector(255,255,255))
	CustomGameEventManager:Send_ServerToAllClients("S2C_CITY_DIYA",{itemIndex = itemIndex,opt = 0})
	if not dontEffect then
		ModifyGoldLtx(id,-needgold)
	end
	return true
end
function M.getCitiesCanLvup( id )
	local mycities = M.getCitiesById(id)
	local ret = {}
	for _,city in ipairs(mycities) do
		if city.build then
			local bSuited,count = block.checkSuit(city.city,id)
			if bSuited then
				local needcities = block.getCitiesBySuit(city.suit)
				local minlv = 10
				local lvt = {}
				for __,cityid in ipairs(needcities) do
					local needcity = M.getCityById(cityid)
					table.insert(lvt,needcity)
				end
				table.sort(lvt,function ( a,b )
					return a.lv < b.lv
				end)
				if lvt[1].lv < #city.build then
					table.insert(ret,lvt[1].city)
					for i=2,#lvt do
						if lvt[i].lv == lvt[1].lv then
							table.insert(ret,lvt[i].city)
						end
					end
				end
			end
		end
	end
	return ret
end

function M.getCitiesCanLvdown( id )
	local mycities = M.getCitiesById(id)
	local ret = {}
	for _,city in ipairs(mycities) do
		if city.build then
			local bSuited,count = block.checkSuit(city.city,id)
			if bSuited then
				local needcities = block.getCitiesBySuit(city.suit)
				local minlv = 10
				local lvt = {}
				for __,cityid in ipairs(needcities) do
					local needcity = M.getCityById(cityid)
					table.insert(lvt,needcity)
				end
				table.sort(lvt,function ( a,b )
					return a.lv > b.lv
				end)
				--if lvt[1] then
				if lvt[1].lv > 1 then
					table.insert(ret,lvt[1].city)
					for i=2,#lvt do
						if lvt[i].lv == lvt[1].lv then
							table.insert(ret,lvt[i].city)
						end
					end
				end
				--end
				
			end
		end
	end
	return ret
end

function M.getCitiesCanDiya( id )
	local ret = {}
	local mycities = M.getCitiesById(id)
	for i,city in ipairs(mycities) do
		if not city.diya then
			table.insert(ret,city.city)
		end
	end
	return ret
end

function M.getCitiesCanShuhui( id )
	local ret = {}
	local mycities = M.getCitiesById(id)
	for i,city in ipairs(mycities) do
		if city.diya then
			table.insert(ret,city.city)
		end
	end
	return ret
end

function M.getCityLvById( id )
	return GameRules.blocks[id].lv
end
function M.hasChezhanToTravel( id )
	local mycities = M.getCitiesById(id)
	local count = 0
	for i,city in ipairs(mycities) do
		if city.suit == 2 then
			count = count + 1
		end
	end
	if count >= 2 then
		return true
	end
	return false
end
function M.doChoice( id,cityid,opt )
	
	if opt == 1 then
		
		local city = GameRules.blocks[cityid]
		local gold = city.gold or 0
		local curgold = _getGold(id)
		if curgold < gold then
			local player = PlayerResource:GetPlayer(id)
			CustomGameEventManager:Send_ServerToPlayer(player,"S2C_ERROR_MSG",{text="#TIP_NO_GOLD"})
		else
			ModifyGoldLtx(id,-gold)
			M.addCityById(id,cityid)
			CustomGameEventManager:Send_ServerToAllClients("S2C_CHOICE_DONE",{})
		end
		GameRules.custom_state = STATE_NONE
	elseif opt == 2 then
		M.startPM(id,cityid)
		CustomGameEventManager:Send_ServerToAllClients("S2C_CHOICE_DONE",{})
	end
end
--开始交易
function M.startTrade( id1,id2 )
	local p1 = M.getCitiesById(id1)
	local p2 = M.getCitiesById(id2)
	GameRules.tradingData = {data={cities={},gold={}},sure={}}
	GameRules.tradingData.sure[id1] = false
	GameRules.tradingData.sure[id2] = false
	GameRules.custom_state = STATE_TRADING
	EmitGlobalSound("General.Buy")
	CustomGameEventManager:Send_ServerToAllClients("C2S_REQUEST_TRADE",{p1 = p1,p2 = p2,id1=id1,id2=id2})
end
--物品添加到交易区域中
function M.pushTrading( itemIndex,owner,isGold )
	GameRules.tradingData.data.cities[owner] = GameRules.tradingData.data.cities[owner] or {}
	GameRules.tradingData.data.gold = GameRules.tradingData.data.gold or {}
	if isGold then
		GameRules.tradingData.data.gold[owner] = itemIndex
		--ModifyGoldLtx(owner,-itemIndex)
	else
		--M.removeCityById(owner,itemIndex)
		table.insert(GameRules.tradingData.data.cities[owner],itemIndex)
	end
	
	--刷新UI
	CustomGameEventManager:Send_ServerToAllClients("C2S_PUSH_GOODS",{itemIndex = itemIndex,owner = owner,gold = isGold})
end
--不能退回物品，只能取消交易
function M.cancleTrade( id,bol )
	print("M.cancleTrade")
	local isDoingman = false
	for i,v in pairs(GameRules.tradingData.sure) do
		if id == i then
			isDoingman = true
		end
	end
	if isDoingman then
		GameRules.custom_state = STATE_NONE
		GameRules.tradingData = {data={cities={},gold={}},sure={}}
		if bol then
			CustomGameEventManager:Send_ServerToAllClients("C2S_CANCLE_TRADE",{})
		end
	end
end
--交易完成
function M.completeTrade(  )
	local ids = {}
	for k,v in pairs(GameRules.tradingData.sure) do
		table.insert(ids,k)
	end
	-- dump(GameRules.tradingData,"tradingData = ")
	-- dump(ids,"ids = ")
	local id1 = ids[1]
	local id2 = ids[2]
	if not id2 then
		id2 = id1
	end
	local cities1 = GameRules.tradingData.data.cities[id1] or {}
	local cities2 = GameRules.tradingData.data.cities[id2] or {}
	local gold1 = GameRules.tradingData.data.gold[id1] or 0
	local gold2 = GameRules.tradingData.data.gold[id2] or 0

	--完成交易  先从玩家1移除，再添加到玩家2
	for i,v in ipairs(cities1) do
		M.removeCityById(id1,v)
		M.addCityById(id2,v)
	end
	for i,v in ipairs(cities2) do
		M.removeCityById(id2,v)
		M.addCityById(id1,v)
	end

	ModifyGoldLtx(id1,-gold1,id2)
	ModifyGoldLtx(id1,gold2,id2)

	M.cancleTrade(id1,true)
end
--确认交易
function M.sureTrade( owner )
	if not GameRules.tradingData.sure[owner] then
		GameRules.tradingData.sure[owner] = true
	else
		local player = PlayerResource:GetPlayer(owner)
		CustomGameEventManager:Send_ServerToPlayer(player,"S2C_ERROR_MSG",{text="#TIP_HAS_SURED"})
	end
	for k,v in pairs(GameRules.tradingData.sure) do
		if not v then
			return false
		end
	end
	--已经双方确认
	M.completeTrade()
end

function M.initPM(  )
	--拍卖纪录
	GameRules.pm_infos = {
		cityid = 0, --拍卖的是哪个地皮
		gold = 0, --当前所出到的金币数
		owner = nil, --当前操作玩家
		entindex = -1, --记录地皮unit  其实不用
		infos = {
			--每个玩家的拍卖信息
		},
		giveups = {
			--放弃的玩家
		},
		rounds = 0, --拍卖了多少轮
	}
end
--开始拍卖
function M.startPM( id,cityid )
	M.initPM()
	GameRules.custom_state = STATE_PAIMAI
	GameRules.pm_infos.cityid = cityid
	GameRules.pm_infos.owner = id
	GameRules.pm_infos.gold = 0
	GameRules.pm_infos.entindex = GameRules.blocks[cityid].unit:entindex()
	--一旦開始拍賣直接终止回合计时器
	gameControl.doAction()
	M.changePlayer(id,true)
	local city = M.getCityById(cityid)
	CustomGameEventManager:Send_ServerToAllClients("C2S_REQUEST_PAIMAI",{citydata=city,cityinfo=GameRules.pm_infos,lvdesc=LVDESC[city.suit]})
end

function M.changePlayer(id,bChange)
	if GameRules.pm_timer then
		unregisterTimer(GameRules.pm_timer)
		GameRules.pm_timer = nil
	end
	if GameRules.round_timer then
		unregisterTimer(GameRules.round_timer)
		GameRules.round_timer = nil
	end
	GameRules.pm_infos.owner = id
	if not bChange then
		CustomGameEventManager:Send_ServerToAllClients("S2C_PAIMAI_CHANGE_PLAYER",{id=id})
	end
	local name = PlayerResource:GetPlayerName(id)
	GameRules.pm_timer = createTimerBar(20,function() 
		M.giveupPM(id)
		
		--现在轮到%s出价
	end,"#TIP_NEXT_PM",{name})
end

function M.getNextId( idx )
	local record = {} --纪录已经放弃的玩家，如果超过#playerlist就自动放弃
	while true do
		idx = idx + 1
		if idx > #GameRules.playerlist then
			idx = 1
		end
		local id = GameRules.playerlist[idx]
		local bf = true
		for i,v in ipairs(GameRules.pm_infos.giveups) do
			if v == id then
				idx = idx + 1
				bf = false
				break
			end
		end
		if not bf then
			--该玩家放弃了
			if record[id] then
				--全部都放弃了  因为已经找了一个圈了  跳出循环
				return false
			else
				record[id] = true
			end
		else
			--有玩家没有放弃
			return id
		end
		
	end
end

function M.checkPMCompleted()
	local giveups = GameRules.pm_infos.giveups
	local playerlist = GameRules.playerlist
	if #giveups == #playerlist-1 then
		for _,id in ipairs(playerlist) do
			local b = false
			for _,v in ipairs(giveups) do
				if v == id then
					b = true
					break
				end
			end
			if not b then
				--扣除金钱，添加地皮
				local cityid = GameRules.pm_infos.cityid
				local gold = GameRules.pm_infos.gold
				M.addCityById(id,cityid)
				ModifyGoldLtx(id,-gold)
				break
			end
		end
		return true
	end
	return false
end
--结束拍卖之后需要继续游戏
function M.canclePM()
	CustomGameEventManager:Send_ServerToAllClients("C2S_PAIMAI_END",{})
	GameRules.custom_state = STATE_NONE
	gameControl.resumeRound(GameRules.curPlayer,GameRules.last_round_timer)--继续之前未结束的回合
end

function M.surePM( id,gold )
	if gold > GameRules.pm_infos.gold and M.checkPM(id) then
		GameRules.pm_infos.gold = gold
		M.newPMInfo(id,gold)
		M.doEndPMRound(id)
	end
end

function M.checkPM( id )
	if GameRules.custom_state == STATE_PAIMAI then
		if GameRules.pm_infos.owner == id then
			return true
		end
	end
	return false
end

function M.doEndPMRound( id )
	local i = getIndexById(id)
	local newid = M.getNextId(i)
	unregisterTimer(GameRules.pm_timer)
	GameRules.pm_timer = nil
	if M.checkPMCompleted() then
		--拍卖完成
		M.canclePM()
	else
		if newid then
			M.changePlayer(newid)
		else
			--全部都放弃了
			M.canclePM()
		end
	end
	
end

function M.giveupPM( id )
	if M.checkPM(id) then
		table.insert(GameRules.pm_infos.giveups,id)
		M.newPMInfo(id)
		M.doEndPMRound(id)
	end
end
function M.newPMInfo(id,gold)
	if not gold then
		CustomGameEventManager:Send_ServerToAllClients("C2S_PAIMAI_GIVEUP",{id=id})
	else
		local i = getIndexById(id)
		local newid = M.getNextId(i)
		CustomGameEventManager:Send_ServerToAllClients("C2S_PAIMAI",{id=id,gold=gold,nextid=newid})
	end
	-- local idx = getIndexById(id)
	-- M.changePlayer(idx)
end
function M.getCurPMId(  )
	return GameRules.pm_infos.owner
end
--获取下一个无主之地
function M.getCityNoOwner( curPoint )
	local start = curPoint
	while true do
		curPoint = curPoint + 1
		if curPoint > MAX_LEN then
			curPoint = 1
		end
		local city = M.getCityById(curPoint)
		if city.owner == nil and city.gold then
			return curPoint,city
		end
		if curPoint <= start then
			return -1,nil
		end
	end
end


M.initDataSystem()
print("roleData inited")
return M